#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <pthread.h>
#include <unistd.h>

struct ThreadInfo
{
    pthread_t tid;
    std::string name;
};

template <class T>
class ThreadPool
{
private:
    std::queue<T> _tasks;
    std::vector<ThreadInfo> _threads;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    bool _stop = false;

    //初始化资源
    ThreadPool(int num = 10) : _threads(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    //回收线程 并 清理资源
    ~ThreadPool()
    {
        Lock();
        _stop = true;
        pthread_cond_broadcast(&_cond);
        Unlock();

        for (auto &thread : _threads)
        {
            pthread_join(thread.tid, nullptr);
        }
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

public:
    // 禁止拷贝构造和赋值--单例模式
    ThreadPool(const ThreadPool<T> &) = delete;
    ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;

    //单例模式
    //静态成员变量保证线程安全(C++11规定: 如果指令逻辑进入一个未被初始化的声明变量，所有并发执行应当等待该变量完成初始化)
    static ThreadPool<T> *GetInstance(int num = 10)
    {
        static ThreadPool<T> thread_pool(num);
        return &thread_pool;
    }

    // 线程执行的函数
    static void *HandlerTask(void *args)
    {
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
        std::string name = tp->GetThreadName(pthread_self());
        while (true)
        {
            tp->Lock();
            while (tp->IsQueueEmpty() && !tp->_stop)
            {
                tp->ThreadSleep();
            }

            if (tp->_stop && tp->IsQueueEmpty())
            {
                tp->Unlock();
                break;
            }

            T task = tp->Pop();
            tp->Unlock();
            task(); // task封装并需要重载(), 里面调用的就是其执行方法
        }
        return nullptr;
    }

    // 创建一批线程
    void Start()
    {
        int num = _threads.size();
        for (int i = 0; i < num; i++)
        {
            _threads[i].name = "thread-" + std::to_string(i + 1);
            if (pthread_create(&(_threads[i].tid), nullptr, HandlerTask, this) != 0)
            {
                throw std::runtime_error("Failed to create thread");
            }
        }
    }

    // 任务队列 -- 临界资源需要维护线程安全
    T Pop()
    {
        T t = _tasks.front();
        _tasks.pop();
        return t;
    }

    void Push(const T &t)
    {
        {
            Lock();
            _tasks.push(t);
            Unlock();
        }
        Wakeup();
    }

    // 辅助函数
    void Lock() { pthread_mutex_lock(&_mutex); }
    void Unlock() { pthread_mutex_unlock(&_mutex); }
    void Wakeup() { pthread_cond_broadcast(&_cond); }
    void ThreadSleep() { pthread_cond_wait(&_cond, &_mutex); }
    bool IsQueueEmpty() { return _tasks.empty(); }
    std::string GetThreadName(pthread_t tid)
    {
        for (const auto &ti : _threads)
        {
            if (ti.tid == tid)
                return ti.name;
        }
        return "None";
    }
};
